<?php
/**************************************************************************
 *
 *   Copyright 2010 American Public Media Group
 *
 *   This file is part of AIR2.
 *
 *   AIR2 is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   AIR2 is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with AIR2.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

require_once 'AIR2_CRUD_Controller.php';

/**
 * Organization Controller
 *
 * @author rcavis
 * @package default
 */
class Organization_Controller extends AIR2_CRUD_Controller {

    public $base_model_name = 'Organization';
    public $base_view_name  = 'organization';
    public $exposed_relations = array(
        'projects' => 'ProjectOrg',
        'users'    => 'UserOrg',
        'inquiries' => 'Inquiry',
        'activity'  => 'SrcActivity',
        'children' => 'children',
    );
    public $image_proxies = array('logo');
    public $column_whitelist = array('uo_ar_id');
    public $valid_args = array(
        'excl_user' => 'query_excl_user',
        'excl_proj' => 'query_excl_proj',
    );
    public $unique_name_col = 'org_name';
    private $_activity_total_count = 0;


    /**
     * Set the mapped-uuid for ProjectOrgs
     */
    public function begin() {
        parent::begin();
        ProjectOrg::change_uuid_col(true);
    }


    /**
     * Add custom relations to queries to this controller
     *
     * @param AIR2_Query $q
     * @param boolean $deeply (optional)
     */
    protected function _add_query_load_related(&$q, $deeply=true) {
        if (!$this->rel_uri) { // base Organization level
            $q->leftJoin('a.ProjectOrg po');
            $q->leftJoin('po.Project p');
            $q->leftJoin('a.parent r');
        }
        elseif ($this->rel_uri === 'projects') {
            $q->leftJoin('a.Project p');

            // flatten some project fields
            $q->addSelect('p.prj_uuid as prj_uuid');
            $this->extra_field_defs []= array('name' => 'prj_uuid');
            $q->addSelect('p.prj_display_name as prj_display_name');
            $this->extra_field_defs []= array('name' => 'prj_display_name');
        }
        elseif ($this->rel_uri === 'users') {
            $q->leftJoin('a.User u');
            $q->leftJoin('a.AdminRole ar');

            // flatten some user fields
            $q->addSelect('u.user_username as user_username');
            $this->extra_field_defs []= array('name' => 'user_username');
            $q->addSelect('u.user_uuid as user_uuid');
            $this->extra_field_defs []= array('name' => 'user_uuid');
        }
        elseif ($this->rel_uri === 'inquiries') {
            $base_id = $this->_find_base()->org_id;
            $base = 'SELECT o.org_id FROM Organization o WHERE o.org_id = ?';
            $prjs = "SELECT po.porg_prj_id FROM ProjectOrg po WHERE po.porg_org_id IN ($base)";
            $inqs = "SELECT pi.pinq_inq_id FROM ProjectInquiry pi WHERE pi.pinq_prj_id IN ($prjs)";
            $q->where("a.inq_id IN ($inqs)", array($base_id));
        }
        elseif ($this->rel_uri === 'activity') {
            // first, add any "where" conditions
            $q->addWhere('a.sact_actm_id != ?', 22);
            $q->addWhere('a.sact_prj_id = ?', $this->_find_base()->org_default_prj_id);

            // NOTE: To make this anywhere near "fast", we need to first get a
            // list of PK's, then use a WHEREIN on the main query. Otherwise,
            // the JOINs will take a looooooong time.
            $subq = $q->copy()->select('a.sact_id');
            $this->airqargs->process_args($subq, $this->query_args);
            $res = $subq->fetchArray();
            $id_list = array();
            foreach ($res as $sact) {
                $id_list[] = $sact['sact_id'];
            }
            $this->_activity_total_count = $subq->count();

            // now add joins to the real query
            $q->whereIn('a.sact_id', $id_list);
            $q->leftJoin('a.ActivityMaster am');
            $q->leftJoin('a.Source s');
        }

        parent::_add_query_load_related($q, $deeply);
    }


    /**
     * NEVER join CreUser or UpdUser from the activity log! (it's slow)
     *
     * @param AIR2_Query $q      (reference) query to modify
     * @param boolean $deeply (optional) recursively scans any joined components
     */
    protected function _add_query_userstamps(&$q, $deeply=false) {
        if ($this->rel_uri !== 'activity')
            parent::_add_query_userstamps($q, $deeply);
    }


    /**
     * Override to add custom update queries
     *
     * @param Doctrine_Record $record (reference) the record object to modify
     * @param associative-array $data   the radix data to update the record with
     */
    protected function _update_record(&$record, $data) {
        if (!$this->rel_uri) {
            $puuid = isset($data['org_parent_uuid']) ? $data['org_parent_uuid'] : null;
            unset($data['org_parent_uuid']);

            if ($puuid) {
                $parent = $record->getTable()->findOneBy('org_uuid', $puuid);
                if (!$parent) $this->crud_error('Invalid parent Org specified!');
                $record->parent = $parent;
            }
        }
        elseif ($this->rel_uri === 'users') {
            $user_uuid = isset($data['user_uuid']) ? $data['user_uuid'] : null;
            unset($data['user_uuid']);

            if ($user_uuid) {
                $usr = Doctrine::getTable('User')->findOneBy('user_uuid', $user_uuid);
                if (!$usr) $this->crud_error('Invalid User specified!');
                $record->User = $usr;
            }
        }
        parent::_update_record($record, $data);
    }


    /**
     * Custom data and views for html requests
     *
     * @param associative-array $data
     * @param string  $view_name
     * @return string html body
     */
    public function get_html_body($data, $view_name=null) {
        if (!$this->base_uuid) { // redirect to directory
            redirect('directory');
        }
        elseif ($this->base_uuid && !$this->rel_uri) {
            $data = $this->_html_dashboard($data);
        }
        return parent::get_html_body($data, $view_name);
    }


    /**
     * Set the page title
     *
     * @param array   $head
     * @return array
     */
    public function get_html_head($head=array()) {
        if ($this->base_uuid) {
            $name = $this->_find_base()->org_display_name;
            $head['title'] = AIR2_SYSTEM_DISP_NAME." - Organization: $name";
        }
        return $head;
    }


    /**
     * Get data for HTML dashboard
     *
     * @param associative-array $data
     * @return associative-array
     */
    protected function _html_dashboard($data) {
        // children orgs
        $q = $this->build_query($this->base_uuid, 'children');
        $q->orderBy('a.org_name ASc');
        $q->limit(6);
        $chd_data = $this->fetch_data($q, true, true);

        // projects
        $q = $this->build_query($this->base_uuid, 'projects');
        $q->limit(10);
        $prj_data = $this->fetch_data($q, true, true);

        // users
        $q = $this->build_query($this->base_uuid, 'users');
        $q->addOrderBy('u.user_last_name ASC');
        $q->limit(8);
        $usr_data = $this->fetch_data($q, true, true);
        $usr_data['metaData']['sortInfo']['field'] = 'User.user_last_name'; // requires explicit prefix

        // inquiries
        $q = $this->build_query($this->base_uuid, 'inquiries');
        $q->orderBy('a.inq_publish_dtim DESC');
        $q->limit(5);
        $inq_data = $this->fetch_data($q, true, true);

        // inquiry search url
        // NOTE this will match all child orgs too, so make sure total on panel reflects that.
        $inq_srch = $this->uri_for('search/inquiries', array('q' => 'org_name=' . $data['radix']['org_name']));

        // activity list -- NOTE: in this special case we need to set the query
        // args to limit and sort (since activity uses a subquery)
        $this->query_args = array('limit' => 10, 's' => 'sact_dtim DESC');
        $q = $this->build_query($this->base_uuid, 'activity');
        $act_data = $this->fetch_data($q, true, true);
        $act_data['total'] = $this->_activity_total_count;

        // admin roles
        $q = AIR2_Query::create()
        ->from('AdminRole ar')
        ->where("ar.ar_status = 'A'");
        $arl_data = $this->airquery->execute_query($q, array());

        return array(
            'org_uuid' => $this->base_uuid,
            'org_url'  => $this->uri_for('organization').'/'.$this->base_uuid,
            'org_data' => $data,
            'chd_data' => $chd_data,
            'prj_data' => $prj_data,
            'usr_data' => $usr_data,
            'inq_data' => $inq_data,
            'act_data' => $act_data,
            'arl_data'  => $arl_data,
            'inq_srch'  => $inq_srch,
        );
    }


    /**
     * GET parameter 'excl_user' to search for orgs that a user isn't already
     * a member of.
     *
     * @param AIR2_Query $q         query to alter
     * @param string  $excl_uuid user_uuid to exclude from the query
     */
    public function query_excl_user($q, $excl_uuid) {
        $usrq = "SELECT zu.user_id FROM User zu WHERE zu.user_uuid = ?";
        $excl = "SELECT zo.uo_org_id FROM UserOrg zo WHERE zo.uo_user_id = ($usrq)";
        $q->addWhere("a.org_id NOT IN ($excl)", $excl_uuid);
    }


    /**
     * GET parameter 'excl_proj' to search for orgs that aren't already related
     * to a project.
     *
     * @param AIR2_Query $q
     * @param string  $prj_uuid
     */
    public function query_excl_proj($q, $prj_uuid) {
        $prjq = "select prj_id from project where prj_uuid = ?";
        $excl = "select porg_org_id from project_org where porg_prj_id = ($prjq)";
        $q->addWhere("a.org_id NOT IN ($excl)", $prj_uuid);
    }


    /**
     * Provide image proxying for the Organization Logo
     *
     * @param string  $uuid    identifier of base model
     * @param string  $rel_uri uri of related model
     * @return radix (list) and metaData
     */
    public function crud_GET_list_related($uuid, $rel_uri) {
        if ($rel_uri != 'logo')
            return parent::crud_GET_list_related ($uuid, $rel_uri);

        // fetch and proxy the "logo"
        $this->base_uuid = $uuid;
        $logo = $this->_find_base()->org_logo_uri;
        air2_proxy_image($logo, $this->uri_for('css/img/not_found_org.png'));
    }


}
